﻿#include "Drawer.h"

Text Drawer::initText(
    FT_Face& font,
    Color color,
	uint8_t alpha,
    float frame_size_x,
    float frame_size_y,
    int loc_x,
    int loc_y,
    Anchor anchor,
    float anchor_x,
    float anchor_y,
	bool horizontal,
	float line_spacing,
	TextAlignment alignment,
    GLuint shader_program
) {
	Text text;
	text.font = font;
	text.shader_program = shader_program;
	text.loc_x = loc_x;
	text.loc_y = loc_y;
	text.frame_size_x = frame_size_x;
	text.frame_size_y = frame_size_y;
	text.color = color;
	text.alpha = alpha;
	text.horizontal = horizontal;
	text.alignment = alignment;
	text.line_spacing = line_spacing;
	switch (anchor) {
	case Anchor::NW:
		text.anchor_x = 0;
		text.anchor_y = 0;
		break;
	case Anchor::N:
		text.anchor_x = 0.5;
		text.anchor_y = 0;
		break;
	case Anchor::NE:
		text.anchor_x = 1;
		text.anchor_y = 0;
		break;
	case Anchor::W:
		text.anchor_x = 0;
		text.anchor_y = 0.5;
		break;
	case Anchor::CENTER:
		text.anchor_x = 0.5;
		text.anchor_y = 0.5;
		break;
	case Anchor::E:
		text.anchor_x = 1;
		text.anchor_y = 0.5;
		break;
	case Anchor::SW:
		text.anchor_x = 0;
		text.anchor_y = 1;
		break;
	case Anchor::S:
		text.anchor_x = 0.5;
		text.anchor_y = 1;
		break;
	case Anchor::SE:
		text.anchor_x = 1;
		text.anchor_y = 1;
		break;
	case Anchor::FREE:
		text.anchor_x = (anchor_x + 1) * 0.5;
		text.anchor_y = (anchor_y + 1) * 0.5;
		break;
	default:
		throw "未知的锚点类型。";
	}

	// 设置视口和投影
	glViewport(0, 0, frame_size_x, frame_size_y);
	text.projection = glm::ortho(0.0f, static_cast<float>(frame_size_x), static_cast<float>(frame_size_y), 0.0f, -1.0f, 1.0f);

	// 准备顶点数据
	float x = 0;
	float y = 0;
	float w = frame_size_x;
	float h = frame_size_y;
	float vertices[] = {
		// 位置          // 纹理坐标（Y翻转）
		x,     y,      0.0f, 1.0f,
		x + w, y,      1.0f, 1.0f,
		x,     y + h,  0.0f, 0.0f,
		x,     y + h,  0.0f, 0.0f,
		x + w, y,      1.0f, 1.0f,
		x + w, y + h,  1.0f, 0.0f
	};

	// 创建VAO/VBO
	glGenVertexArrays(1, &text.vao);
	glGenBuffers(1, &text.vbo);
	glBindVertexArray(text.vao);
	glBindBuffer(GL_ARRAY_BUFFER, text.vbo);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

	// 位置属性
	glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
	glEnableVertexAttribArray(0);
	// 纹理坐标属性
	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));
	glEnableVertexAttribArray(1);
	return text;
}

void _draw_horizontal_text(Text& text, std::string name, GLuint target_fbo, GLuint target_texture) {
	std::vector<uint32_t> _utf8_to_codepoints(const std::string str);
	FT_Face _load_char(FT_FaceRec_ *font, uint32_t cp);

	auto codepoints = _utf8_to_codepoints(name);
	FT_Face font = text.font;

	uint8_t* text_mat = new uint8_t[text.frame_size_x * text.frame_size_y * 4];
	memset(text_mat, 0, text.frame_size_x * text.frame_size_y * 4);

	// 计算行高和字体度量
	int baseline = font->size->metrics.ascender >> 6;
	int descender = -font->size->metrics.descender >> 6;
	int line_height = baseline + descender;
	int line_spacing = static_cast<int>(line_height * text.line_spacing);

	double _x = text.loc_x;
	double _y = text.loc_y;

	// 分割文本到多行
	std::vector<std::vector<uint32_t>> lines;
	std::vector<uint32_t> current_line;

	for (uint32_t cp : codepoints) {
		if (cp == '\n') { // 换行符处理
			if (!current_line.empty()) {
				lines.push_back(current_line);
				current_line.clear();
			}
		}
		else {
			current_line.push_back(cp);
		}
	}
	if (!current_line.empty()) {
		lines.push_back(current_line);
	}

	// 计算多行文本的总高度
	int total_height = static_cast<int>(lines.size() * line_height + (lines.size() - 1) * line_spacing);

	// 计算起始位置（考虑锚点和总高度）
	Location nw_corner = {
		.x = static_cast<int>(_x - text.anchor_x * text.frame_size_x),
		.y = static_cast<int>(_y - text.anchor_y * total_height)
	};

	// 逐行渲染文本
	int current_y = nw_corner.y;

	for (const auto& line_codepoints : lines) {
		if (line_codepoints.empty()) {
			current_y += line_spacing;
			continue;
		}

		// 计算当前行的宽度
		int line_width = 0;
		FT_UInt prev_glyph = 0;
		for (uint32_t cp : line_codepoints) {
			font = _load_char(text.font, cp);
			if (prev_glyph) {
				FT_Vector delta;
				FT_Get_Kerning(font, prev_glyph, font->glyph->glyph_index, FT_KERNING_DEFAULT, &delta);
				line_width += delta.x >> 6;
			}

			line_width += (font->glyph->advance.x >> 6);
			prev_glyph = font->glyph->glyph_index;
		}

		// 计算行起始x位置（根据文本对齐方式）
		int start_x = 0;
		switch (text.alignment) {
		case TextAlignment::LEFT:
			start_x = nw_corner.x;
			break;
		case TextAlignment::CENTER:
			start_x = nw_corner.x + (text.frame_size_x - line_width) / 2;
			break;
		case TextAlignment::RIGHT:
			start_x = nw_corner.x + text.frame_size_x - line_width;
			break;
		default:
			throw "错误的对齐方式。";
		}

		int x = start_x;
		prev_glyph = 0;

		for (uint32_t cp : line_codepoints) {
			font = _load_char(text.font, cp);
			FT_Bitmap* bitmap = &font->glyph->bitmap;

			// 处理字间距
			if (prev_glyph) {
				FT_Vector delta;
				FT_Get_Kerning(font, prev_glyph, font->glyph->glyph_index, FT_KERNING_DEFAULT, &delta);
				x += delta.x >> 6;
			}
			prev_glyph = font->glyph->glyph_index;

			int y_offset = baseline - font->glyph->bitmap_top;

			// 渲染当前字符
			for (int i = 0; i < bitmap->rows; ++i) {
				int y_pos = current_y + y_offset + i;
				for (int j = 0; j < bitmap->width; ++j) {
					if (y_pos >= 0 && y_pos < text.frame_size_y &&
						(x + j) >= 0 && (x + j) < text.frame_size_x) {

						size_t location = y_pos * text.frame_size_x + (x + j);
						uint8_t* pixel = text_mat + location * 4;

						double val = bitmap->buffer[i * bitmap->width + j] / 255.0;
						pixel[0] = val * text.color.x;
						pixel[1] = val * text.color.y;
						pixel[2] = val * text.color.z;
						pixel[3] = val > 0 ? text.alpha : 0;
					}
				}
			}

			x += (font->glyph->advance.x >> 6);
		}

		// 移动到下一行
		current_y += line_spacing + line_height;
	}
	GLuint temp_texture;
	glBindFramebuffer(GL_FRAMEBUFFER, target_fbo);
	glViewport(0, 0, text.frame_size_x, text.frame_size_y);

	if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
		throw "";
	}
	glGenTextures(1, &temp_texture);
	glBindTexture(GL_TEXTURE_2D, temp_texture);
	glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // 处理行对齐
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, text.frame_size_x, text.frame_size_y, 0, GL_RGBA, GL_UNSIGNED_BYTE, text_mat);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 恢复默认

	// 渲染设置
	glUseProgram(text.shader_program);
	GLint proj_loc = glGetUniformLocation(text.shader_program, "projection");
	glUniformMatrix4fv(proj_loc, 1, GL_FALSE, &text.projection[0][0]);

	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, temp_texture);
	GLint tex_loc = glGetUniformLocation(text.shader_program, "textureBitmap");
	glUniform1i(tex_loc, 0);

	// 绘制
	glBindVertexArray(text.vao);
	glDrawArrays(GL_TRIANGLES, 0, 6);

	// 清理资源
	glDeleteTextures(1, &temp_texture);
	glBindFramebuffer(GL_FRAMEBUFFER, 0);
	glBindTexture(GL_TEXTURE_2D, 0);
	delete[] text_mat;
}

void _draw_vertical_text(Text& text, std::string name, GLuint target_fbo, GLuint target_texture) {
	std::vector<uint32_t> _utf8_to_codepoints(const std::string str);
	bool is_western_character(uint32_t codepoint);
	FT_Face _load_char(FT_FaceRec_ *font, uint32_t cp);

	auto codepoints = _utf8_to_codepoints(name);
	FT_Face font = text.font;

	uint8_t* text_mat = new uint8_t[text.frame_size_x * text.frame_size_y * 4];
	memset(text_mat, 0, text.frame_size_x * text.frame_size_y * 4);

	// 计算字体度量
	int baseline = font->size->metrics.ascender >> 6;
	int descender = -font->size->metrics.descender >> 6;
	int char_height = baseline + descender;
	int column_spacing = static_cast<int>(char_height * text.line_spacing);

	double _x = text.loc_x;
	double _y = text.loc_y;

	// 分割文本到多列（每列是一行）
	std::vector<std::vector<uint32_t>> columns;
	std::vector<uint32_t> current_column;

	for (uint32_t cp : codepoints) {
		if (cp == '\n') { // 换行符表示新的一列
			if (!current_column.empty()) {
				columns.push_back(current_column);
				current_column.clear();
			}
		}
		else {
			current_column.push_back(cp);
		}
	}
	if (!current_column.empty()) {
		columns.push_back(current_column);
	}

	// 计算每列的最大宽度
	std::vector<int> column_widths;
	int max_column_width = 0;
	int total_width = 0;

	for (const auto& col_codepoints : columns) {
		int col_width = 0;
		for (uint32_t cp : col_codepoints) {
			bool is_western = is_western_character(cp);
			font = _load_char(text.font, cp);
			col_width = std::max(col_width, static_cast<int>(is_western ? font->glyph->bitmap.rows : font->glyph->bitmap.width));
		}
		column_widths.push_back(col_width);
		max_column_width = std::max(max_column_width, col_width);
		total_width += col_width;
	}

	// 添加列间距
	if (!columns.empty()) {
		total_width += static_cast<int>((columns.size() - 1) * column_spacing);
	}

	// 计算起始位置（考虑锚点）
	Location nw_corner = {
		.x = static_cast<int>(_x - text.anchor_x * total_width),
		.y = static_cast<int>(_y - text.anchor_y * text.frame_size_y)
	};
	int current_x = nw_corner.x;

	// 逐列渲染文本

	for (int col_idx = columns.size() - 1; col_idx >= 0; col_idx--) {
		const auto& col_codepoints = columns[col_idx];
		FT_UInt prev_glyph = 0;
		current_x += column_widths[col_idx];
		if (col_codepoints.empty()) {
			current_x += column_spacing;
			continue;
		}

		// 计算列高度（所有字符高度之和）
		int column_height = 0;
		for (uint32_t cp : col_codepoints) {
			bool is_western = is_western_character(cp);
			font = _load_char(text.font, cp);
			column_height += font->glyph->bitmap.rows;
		}
		int advance = (font->glyph->advance.x >> 6);

		// 计算列起始y位置（根据垂直对齐方式）
		int start_y = 0;
		switch (text.alignment) {
		case TextAlignment::TOP:
			start_y = nw_corner.y;
			break;
		case TextAlignment::CENTER:
			start_y = nw_corner.y + (text.frame_size_y - column_height) / 2;
			break;
		case TextAlignment::BOTTOM:
			start_y = nw_corner.y + text.frame_size_y - column_height;
			break;
		default:
			throw "错误的对齐方式。";
		}

		int y = start_y;
		int delta_y = 0;

		// 添加字符间距
		if (prev_glyph) {
			FT_Vector delta;
			FT_Get_Kerning(font, prev_glyph, font->glyph->glyph_index, FT_KERNING_DEFAULT, &delta);
			delta_y = delta.x >> 6;
			y += delta_y;
		}
		prev_glyph = font->glyph->glyph_index;

		for (uint32_t cp : col_codepoints) {
			bool is_western = is_western_character(cp);

			// 设置旋转（仅对西文字符）
			FT_Matrix matrix;
			if (is_western) {
				matrix.xx = 0;         // 旋转90度
				matrix.xy = 0x10000;  // -1.0
				matrix.yx = -0x10000;   // 1.0
				matrix.yy = 0;
				FT_Set_Transform(font, &matrix, nullptr);
			}

			font = _load_char(text.font, cp);
			FT_Bitmap* bitmap = &font->glyph->bitmap;

			// 恢复单位矩阵
			if (is_western) {
				matrix.xx = 0x10000;  // 1.0
				matrix.xy = 0;
				matrix.yx = 0;
				matrix.yy = 0x10000;  // 1.0
				FT_Set_Transform(font, &matrix, nullptr);
			}

			// 计算实际宽高（旋转后可能变化）
			int char_width = cp == ' ' ? advance : bitmap->rows;

			// 水平居中偏移量（在列内）
			int x_offset = baseline + font->glyph->bitmap_left;
			if (cp == ' ') {
				goto skip_drawing;
			}

			// 绘制字符
			for (int col = 0; col < char_height; col++) {
				int global_x = current_x + x_offset + col;
				for (int row = 0; row < char_width; row++) {
					if (global_x >= 0 && global_x < text.frame_size_x) {
						int global_y = y + row;
						if (global_y >= 0 && global_y < text.frame_size_y) {
							size_t location = global_y * text.frame_size_x + global_x;
							uint8_t* pixel = text_mat + location * 4;

							// 计算位图索引（考虑旋转）
							int src_row, src_col;
							src_row = row;
							src_col = col;

							double val = 0.0;
							if (src_col >= 0 && src_col < bitmap->width &&
								src_row >= 0 && src_row < bitmap->rows) {
								val = bitmap->buffer[src_row * bitmap->width + src_col] / 255.0;
							}

							pixel[0] = val * text.color.x;
							pixel[1] = val * text.color.y;
							pixel[2] = val * text.color.z;
							pixel[3] = val > 0 ? text.alpha : 0;
						}
					}
				}
			}
			skip_drawing:
			// 更新垂直位置
			y += char_width + delta_y;
		}

		// 移动到下一列
		current_x += column_spacing;
	}

	// 创建纹理并渲染
	GLuint temp_texture;
	glGenTextures(1, &temp_texture);
	glBindTexture(GL_TEXTURE_2D, temp_texture);
	glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // 处理行对齐
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, text.frame_size_x, text.frame_size_y,
		0, GL_RGBA, GL_UNSIGNED_BYTE, text_mat);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 恢复默认

	// 渲染设置
	glUseProgram(text.shader_program);
	GLint proj_loc = glGetUniformLocation(text.shader_program, "projection");
	glUniformMatrix4fv(proj_loc, 1, GL_FALSE, &text.projection[0][0]);

	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, temp_texture);
	GLint tex_loc = glGetUniformLocation(text.shader_program, "textureBitmap");
	glUniform1i(tex_loc, 0);

	// 绘制
	glBindFramebuffer(GL_FRAMEBUFFER, target_fbo);
	glBindVertexArray(text.vao);
	glDrawArrays(GL_TRIANGLES, 0, 6);

	// 清理资源
	glDeleteTextures(1, &temp_texture);
	glBindTexture(GL_TEXTURE_2D, 0);
	delete[] text_mat;
}

FT_FaceRec_ *_load_char(FT_FaceRec_ *font, uint32_t cp) {
	FT_Load_Char(font, cp, FT_LOAD_RENDER);
	return font;
}

Location _calculate_text_size(FT_Face& font, std::string name) {
	std::vector<uint32_t> _utf8_to_codepoints(const std::string str);
	int lineHeight = font->size->metrics.height >> 6;
	auto codepoints = _utf8_to_codepoints(name);

	int width = 0, max_height = 0;
	FT_UInt prev_glyph = 0;
	for (uint32_t cp : codepoints) {
		FT_Load_Char(font, cp, FT_LOAD_DEFAULT);
		FT_Render_Glyph(font->glyph, FT_RENDER_MODE_NORMAL);

		// 计算字间距（kerning）
		if (prev_glyph) {
			FT_Vector delta;
			FT_Get_Kerning(font, prev_glyph, font->glyph->glyph_index, FT_KERNING_DEFAULT, &delta);
			width += delta.x >> 6;
		}
		prev_glyph = font->glyph->glyph_index;

		width += font->glyph->advance.x >> 6;
		max_height = std::max<int>(max_height, static_cast<int>(font->glyph->metrics.height >> 6));
	}
	return Location{ width, max_height };
}

FT_Face _check_font(FT_Face &font, std::vector<uint32_t> &codepoints, bool strict) {
	return font;
}

bool is_western_character(uint32_t codepoint) {
	// 基本拉丁字母（ASCII）
	if (codepoint >= 0x0020 && codepoint <= 0x007A) return true;

	// 拉丁扩展-A（西欧语言）
	if (codepoint >= 0x00C0 && codepoint <= 0x00FF) return true;

	// 拉丁扩展-B（特殊字符）
	if (codepoint >= 0x0180 && codepoint <= 0x024F) return true;

	// 数字和常用标点
	if (codepoint >= 0x0030 && codepoint <= 0x0039) return true;
	if (codepoint >= 0x0020 && codepoint <= 0x002F) return true;
	if (codepoint >= 0x003A && codepoint <= 0x0040) return true;

	return false;
}

std::vector<uint32_t> _utf8_to_codepoints(const std::string str) {
	std::vector<uint32_t> codepoints;
	for (size_t i = 0; i < str.size();) {
		uint32_t codepoint = 0;
		if ((str[i] & 0x80) == 0x00) {        // 1字节
			codepoint = str[i++];
		}
		else if ((str[i] & 0xE0) == 0xC0) {  // 2字节
			codepoint = ((str[i++] & 0x1F) << 6) | (str[i++] & 0x3F);
		}
		else if ((str[i] & 0xF0) == 0xE0) {  // 3字节
			codepoint = ((str[i++] & 0x0F) << 12) | ((str[i++] & 0x3F) << 6) | (str[i++] & 0x3F);
		}
		else if ((str[i] & 0xF8) == 0xF0) {  // 4字节
			codepoint = ((str[i++] & 0x07) << 18) | ((str[i++] & 0x3F) << 12) | ((str[i++] & 0x3F) << 6) | (str[i++] & 0x3F);
		}
		codepoints.push_back(codepoint);
	}
	return codepoints;
}

std::string _subreplace(std::string resource_str, std::string sub_str, std::string new_str) {
	std::string dst_str = resource_str;
	std::string::size_type pos = 0;
	while ((pos = dst_str.find(sub_str)) != std::string::npos) {
		dst_str.replace(pos, sub_str.length(), new_str);
	}
	return dst_str;
}

void Drawer::drawText(Text& text, std::string name, GLuint target_fbo, GLuint target_texture) {
	if (name.empty())return;
	std::string new_name = _subreplace(name, "<br>", "\n");
	if (text.horizontal) _draw_horizontal_text(text, new_name, target_fbo, target_texture);
	else _draw_vertical_text(text, new_name, target_fbo, target_texture);
}
